package com.example.lock;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class WatchCallback implements AsyncCallback.StringCallback, Watcher, AsyncCallback.Children2Callback, AsyncCallback.StatCallback {

    private String path = "/lock";

    private ZooKeeper zk;

    private String threadName;
    private String name;

    private CountDownLatch cd = new CountDownLatch(1);

    public WatchCallback(String threadName, ZooKeeper zk) {
        this.threadName = threadName;
        this.zk = zk;
    }

    public void tryLock() {

        zk.create(path, threadName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL, this, "ss");

        try {
            cd.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void unLock() {
        if (name != null) {
            try {
                zk.delete(name, -1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (KeeperException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void processResult(int rc, String path, Object ctx, String name) {
        if (name != null) {
            this.name = name;
            zk.getChildren("/", false, this, "aaa");

        }

    }

    @Override
    public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
//        System.out.println(threadName + " name  " + name + " list  " + children);
        if (children == null || children.size() == 0) {
            return;
        }

        Collections.sort(children);
        int index = children.indexOf(name.substring(1));

        if (index == 0) {
            System.out.println(threadName + " name  " + name);
            try {
                /**
                 * 加这一步，是防止countDown后进业务层，业务跑太快 很快删除了当前临时节点，而后边的线程还在与zk进行exists交互，
                 * 交互还没完成，回调还没来得及设置，当回调设置好之后，删除已经发生过了，导致监控的删除事件不能再触发到。
                 *
                 * 加上这一步，就能延迟
                 */
                zk.setData("/", "delay".getBytes(), -1);
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cd.countDown();

        } else {

            zk.exists("/" + children.get(index - 1), this, this, "ccc");
        }

    }

    @Override
    public void process(WatchedEvent event) {
        switch (event.getType()) {
            case None:
                break;
            case NodeCreated:
                break;
            case NodeDeleted:

                zk.getChildren("/", false, this, "aaa");


                break;
            case NodeDataChanged:
                break;
            case NodeChildrenChanged:
                break;
            case DataWatchRemoved:
                break;
            case ChildWatchRemoved:
                break;
            case PersistentWatchRemoved:
                break;
        }
    }

    @Override
    public void processResult(int rc, String path, Object ctx, Stat stat) {

    }
}
